/*********************************************************
          File Name:class_derive.cpp
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sun 20 Sep 2015 11:34:17 AM CST
**********************************************************/

#include <iostream>

// another exmaple "http://www.cnblogs.com/qlwy/archive/2011/08/25/2153584.html"

/*
        +-----------------+----------+-----------+---------+
        |Base class       | public   | protected | private |
        +-----------------+----------+-----------+---------+
        |public derived   | public   | protected |   N/A   |
        +-----------------+----------+-----------+---------+
        |private derived  | private  | protected |   N/A   |
        +-----------------+----------+-----------+---------+
        |protected derived| protected| protected |   N/A   |
        +-----------------+----------+-----------+---------+
*/


class base
{
        private:
                int n;
                int get_n() { return n; }
        protected:
                int m;
        public:
                base() = default;
                base(int i): n(i), m(i) {  }
                
                int get_priv_n() { return get_n(); }
                int get_m() { return m; }
};

class derived final: public base
{
        /*
         * private:             // private in `base`
         *      N/A
         * protected:           // protected in `base`
         *      int m;
         */
        public:
                /*              // public in `base`
                 * base() = default;
                 *base(int i): n(i), m(i) {  }
                 *
                 *int get_priv_n() { return get_n(); }
                 *int get_m() { return m; }
                 */
                derived() = default;
                derived(int i): base(i) {  }
};

class derived_1 final: protected base
{
        /*
         * private:     // private in `base`
         *      N/A
         * protected:   // protected in `base`
         *      int m;
         *
         * protected:   // public in `base`
         *      base() = default;
         *      base(int i): n(i), m(i) {  }
         *
         *      int get_priv_n() { return get_n(); }
         *      int get_m() { return m; }
         */
        public:
                derived_1() = default;
                derived_1(int i): base(i) {  }
};

class derived_2: private base
{
        /*
         * private:     // private in `base`
         *      N/A
         * private:     // public in `base`
         *      base() = default;
         *      base(int i): n(i), m(i) {  }
         *
         *      int get_priv_n() { return get_n(); }
         *      int get_m() { return m; }
         *
         * protected:
         *      int m;
         */
        public:
                derived_2() = default;
                derived_2(int i): base(i) {  }
};

int main()
{
        derived d1(1);          // public derived

        // access public member of `base`, public member of `derived`
        d1.get_m();

        // accesss  private member of `base`, private member of `derived`
         d1.get_n();             // N/A

        // access protected member of `base`, protected member of `derived`
         std::cout << d1.m << std::endl;

        //----------------------------------------------------------

        derived_1 d2(2);        // proctected derived

        // access public member of `base`, protected member of `derived_1`
        d2.get_m();

        // access private member of `base`, private member of `derived_1`
        d2.get_n();

        // access protected member of `base`, protected member of `derived_1`
        std::cout << d2.m << std::endl;

        //---------------------------------------------------------

        derived_2 d3(3);        // privete derived

        // access public member of `base`, private member of `derived_2`
        d3.get_m();

        // access private member of `base`, private member of `dervied_2`
        d3.get_n();

        // access protected member of `base`, protected member of `derived_2`
        std::cout << d3.m << std::endl;

        return 0;
}
